import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;


/**
 * @author Robert C. Duvall, revised by Yaqi Zhang
 */
public class Spring implements Material {
    private Mass myStart;
    private Mass myEnd;
    private double myLength;
    private double myK;
    private double myFixedLength;

    /**
     * @param start start mass
     * @param end end mass
     * @param fixedLength rest length of a string
     * @param kVal springy-ness coefficient of a spring
     */
    public Spring(Mass start, Mass end, double fixedLength, double kVal) {
        myStart = start;
        myEnd = end;
        myFixedLength = fixedLength;
        myK = kVal;
    }

    /**
     * implement the Material.paint.
     * 
     * @param pen pen to draw the spring
     */
    @Override
    public void paint(Graphics2D pen) {
        int xStart = (int) myStart.getCenter().getX();
        int yStart = (int) myStart.getCenter().getY();
        int xEnd = (int) myEnd.getCenter().getX();
        int yEnd = (int) myEnd.getCenter().getY();
        double dx = xStart - xEnd;
        double dy = yStart - yEnd;
        double len = Math.sqrt(dx * dx + dy * dy) - myLength;

        if (Math.abs(len) < 0.001) {
            pen.setColor(Color.BLACK);
        }
        else if (len < 0.0) {
            pen.setColor(Color.BLUE);
        }
        else {
            pen.setColor(Color.RED);
        }
        pen.drawLine(xStart, yStart, xEnd, yEnd);
    }

    /**
     * implement the Material.paint.
     * 
     * @param canvas canvas to draw on
     * @param dt time interval to refresh the screen
     */
    @Override
    public void update(Simulation canvas, double dt) {
        myLength = calLength(myFixedLength);
        Point2D start = myStart.getCenter();
        Point2D end = myEnd.getCenter();
        double dx = start.getX() - end.getX();
        double dy = start.getY() - end.getY();

        // apply hooke's law to each attached mass
        Force f = new Force(Force.angleBetween(dx, dy), myK
                * (myLength - Force.distanceBetween(dx, dy)));
        myStart.applyForce(f);
        f.negate();
        myEnd.applyForce(f);
    }

    /**
     * return the length of the spring.
     * 
     * @param fixedlength the rest length of the spring
     */
    public double calLength(double fixedlength) {
        return fixedlength;
    }

    /**
     * return the id of the spring, which will always be a negtive value.
     */
    @Override
    public int getId() {
        return -1000;
    }

    /**
     * return the start mass.
     */
    public Mass getStart() {
        return myStart;
    }

    /**
     * return the end mass.
     */
    public Mass getEnd() {
        return myEnd;
    }

    /**
     * return the length of this spring.
     */
    public double getLength() {
        return myLength;
    }
}
